package com.mofang.ticketing.user.serve.account.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.mofang.ticketing.common.core.dto.PrimaryIdDTO;
import com.mofang.ticketing.common.core.enums.account.AccountTypeEnum;
import com.mofang.ticketing.common.core.enums.account.BelongEnum;
import com.mofang.ticketing.common.core.exception.BizException;
import com.mofang.ticketing.common.redis.constant.RedisConstant;
import com.mofang.ticketing.common.redis.service.RedisService;
import com.mofang.ticketing.user.mapping.entity.MerchantInfoDO;
import com.mofang.ticketing.user.mapping.entity.SysUserDO;
import com.mofang.ticketing.user.mapping.entity.SysUserRoleDO;
import com.mofang.ticketing.user.mapping.mapper.MerchantInfoDOMapper;
import com.mofang.ticketing.user.mapping.mapper.SysUserDOMapper;
import com.mofang.ticketing.user.mapping.mapper.SysUserRoleDOMapper;
import com.mofang.ticketing.user.serve.account.dto.request.*;
import com.mofang.ticketing.user.serve.account.dto.response.MerchantAccountListPageRespDTO;
import com.mofang.ticketing.user.serve.account.mapper.AccountMapper;
import com.mofang.ticketing.user.serve.account.service.AuthService;
import com.mofang.ticketing.user.serve.account.service.MerchantAccountService;
import com.mofang.ticketing.user.serve.account.service.PlatformAccountService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author LGC
 * @date 2023/3/14 13:41
 */
@Slf4j
@Service
public class MerchantAccountServiceImpl implements MerchantAccountService {
    @Resource
    private SysUserDOMapper sysUserDOMapper;
    @Resource
    private SysUserRoleDOMapper sysUserRoleDOMapper;
    @Resource
    private MerchantInfoDOMapper merchantInfoDOMapper;
    @Resource
    private AccountMapper accountMapper;
    @Resource
    private RedisService redisService;
    @Resource
    private AuthService authService;
    @Resource
    private PlatformAccountService platformAccountService;

    @Override
    public IPage<MerchantAccountListPageRespDTO> merchantAccountListPage(MerchantAccountListPageReqDTO dto) {
        IPage<MerchantAccountListPageRespDTO> pageResult = accountMapper.selectMerchantAccountListPage(dto.getPage().getPage(), dto);
        List<MerchantAccountListPageRespDTO> records = pageResult.getRecords();
        for (MerchantAccountListPageRespDTO record : records) {
            if (record.getAccountType().equals(AccountTypeEnum.MERCHANT_ADMIN.getKey())) {
                record.setMerchantName(accountMapper.selectUserBelongMerchant(record.getId(), record.getBelong())
                        .stream().map(MerchantInfoDO::getMerchantName).collect(Collectors.joining(",")));
            }
            if (record.getAccountType().equals(AccountTypeEnum.MERCHANT_MEMBER.getKey())) {
                MerchantInfoDO merchant = accountMapper.selectUserBelongMerchant(record.getId(), record.getBelong()).get(0);
                record.setMerchantId(merchant.getId());
                record.setMerchantName(merchant.getMerchantName());
            }
        }
        return pageResult;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void merchantAccountAdd(MerchantAccountAddReqDTO dto) {
        platformAccountService.platformAccountAdd(new PlatformAccountAddReqDTO(AccountTypeEnum.MERCHANT_MEMBER.getKey(), dto.getMerchantId(), dto.getRoleId()));
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void merchantAccountUpdate(MerchantAccountUpdateReqDTO dto) {
        platformAccountService.platformAccountUpdate(new PlatformAccountUpdateReqDTO(dto.getId(), dto.getUsername(), dto.getMerchantId(), dto.getRoleId()));
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void merchantAccountEnable(PrimaryIdDTO dto) {
        platformAccountService.platformAccountEnable(dto);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void merchantAccountResetPwd(PrimaryIdDTO dto) {
        platformAccountService.platformAccountResetPwd(dto);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void merchantAccountDel(PrimaryIdDTO dto) {
        platformAccountService.platformAccountDel(dto);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void merchantAccountUpdatePwd(AccountUpdatePwdReqDTO dto) {
        platformAccountService.platformAccountUpdatePwd(dto);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void merchantAccountUpdatePhone(AccountUpdatePhoneReqDTO dto, Long userId) {
        SysUserDO sysUserDO = sysUserDOMapper.selectById(userId);
        if (sysUserDO == null) {
            throw new BizException("账号不存在");
        }
        String oldPhone = dto.getOldPhone();
        String newPhone = dto.getNewPhone();
        if (!oldPhone.equals(sysUserDO.getAccount())) {
            throw new BizException("原手机号输入有误");
        }
        if (!newPhone.equals(dto.getConfirmPhone())) {
            throw new BizException("新手机号前后输入不一致");
        }
        Integer belong = sysUserDO.getBelong();
        Integer accountType = sysUserDO.getAccountType();
        //平台管理员、商户管理员才能修改手机号，商户成员、项目成员不显示第二行的绑定手机号
        if (!belong.equals(BelongEnum.MERCHANT.getKey())) {
            throw new BizException("该账号非商户商户及账号，不能修改手机号");
        }
        if (!accountType.equals(AccountTypeEnum.MERCHANT_ADMIN.getKey())) {
            throw new BizException("该账号非商户管理员账号，不能修改手机号");
        }
        // 初始化平台管理员手机号不能修改，平台管理员修改手机号不能添加已有手机号号注册，商户管理员修改手机号不能添加已成为平台级的手机号
        Long count = new LambdaQueryChainWrapper<>(sysUserDOMapper)
                .eq(SysUserDO::getAccount, newPhone)
                .eq(SysUserDO::getBelong, BelongEnum.PLATFORM.getKey()).count();
        if (count > 0) {
            throw new BizException("商户管理员修改手机号，不能添加已成为平台级的手机号");
        }
        // todo 如果新手机号已经存在为商户管理员，替换旧手机号商户用户关联关系 为 新手机号商户用户关联关系，更新旧手机商户管理员账号为新手机号，删除旧手机号账号
        // todo 如果新手机号不存在，替换旧手机账号为新手机号，更新旧手机商户管理员账号为新手机号
        // 旧手机号管理员用户商户关联关系
        List<SysUserRoleDO> oldPhoneMerchantList = accountMapper.selectUserMerchant(sysUserDO.getId(), BelongEnum.MERCHANT.getKey());
        // 获取新手机商户管理员账号是否存在
        SysUserDO newPhoneMerchantAdminAccount = new LambdaQueryChainWrapper<>(sysUserDOMapper)
                .eq(SysUserDO::getAccount, newPhone)
                .eq(SysUserDO::getBelong, BelongEnum.MERCHANT.getKey())
                .eq(SysUserDO::getAccountType, AccountTypeEnum.MERCHANT_ADMIN.getKey()).one();
        if (newPhoneMerchantAdminAccount != null) {
            // 替换旧手机号商户用户关联关系 为 新手机号商户用户关联关系，更新旧手机商户管理员账号为新手机号
            for (SysUserRoleDO sysUserRoleDO : oldPhoneMerchantList) {
                sysUserRoleDO.setUserId(newPhoneMerchantAdminAccount.getId());
                sysUserRoleDOMapper.updateById(sysUserRoleDO);
            }
            // 删除旧手机号账号
            sysUserDOMapper.deleteById(sysUserDO.getId());
        } else {
            // 替换旧手机账号为新手机号
            boolean updateAccount = authService.updateAccount(sysUserDO, newPhone);
            if (!updateAccount) {
                throw new BizException("更新账号失败");
            }
        }
        // 更新旧手机商户管理员账号为新手机号
        for (SysUserRoleDO sysUserRoleDO : oldPhoneMerchantList) {
            new LambdaUpdateChainWrapper<>(merchantInfoDOMapper)
                    .set(MerchantInfoDO::getAdminAccount, newPhone)
                    .eq(MerchantInfoDO::getId, sysUserRoleDO.getMerchantId()).update();
        }

        redisService.del(String.format(RedisConstant.LOGIN_INFO_KEY, oldPhone));
        redisService.del(String.format(RedisConstant.LOGIN_INFO_KEY, newPhone));
    }
}
